package com.itany.shop.dao.impl;

import com.itany.shop.dao.OrderDao;
import com.itany.shop.entity.Item;
import com.itany.shop.entity.Order;
import com.itany.shop.entity.Product;
import com.itany.shop.entity.User;
import com.itany.shop.exception.DataAccessException;
import com.itany.shop.factory.ObjectFactory;
import com.itany.shop.rowmapper.OrderRowMapper;
import com.itany.shop.util.JDBCTemplate;
import com.itany.shop.util.JDBCUtil;
import com.itany.shop.util.KeyHolder;
import com.itany.shop.util.PreparedStatementCreator;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;

/**
 * @author 石小俊
 * @date 2023年09月21日 15:54
 */
public class OrderDaoImpl implements OrderDao {

    private JDBCTemplate jdbcTemplate = (JDBCTemplate) ObjectFactory.getObject("jdbc");

    @Override
    public Long insertReturnPrimaryKey(Order order) {
        KeyHolder keyHolder = new KeyHolder();
        jdbcTemplate.insertReturnPrimaryKey(new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection conn) throws Exception {
                String sql = new StringBuffer()
                        .append(" insert into ")
                        .append(" t_order")
                        .append("   (no,price,user_id)")
                        .append(" values ")
                        .append("   (?,?,?)")
                        .toString();
                // 获取保存返回主键的状态集
                PreparedStatement ps = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
                // 设置参数
                ps.setString(1, order.getNo());
                ps.setDouble(2, order.getPrice());
                ps.setInt(3, order.getUser().getId());
                return ps;
            }
        }, keyHolder);
        // 假设由于数据库版本不同,导致返回的主键类型是BigInteger
        // 可以直接将BigInteger转换成Long类型
        // BigInteger id = (BigInteger) keyHolder.getKey();
        // return id.longValue();
        return (Long) keyHolder.getKey();
    }

    @Override
    public List<Order> selectByUserId(Integer id) {
        String sql = new StringBuffer()
                .append(" select id,no,price,user_id ")
                .append(" from t_order ")
                .append(" where user_id = ? ")
                .toString();
        List<Order> orders = jdbcTemplate.query(sql, new OrderRowMapper(), id);
        return orders;
    }

    @Override
    public Order selectById(Integer id) {
        String sql = new StringBuffer()
                .append(" select o.id,o.no,o.price,u.username,u.phone,p.name,i.num,i.price 'i.price', ")
                .append(" (select count(1) from t_item where order_id = o.id) count ")
                .append(" from t_order o ")
                .append(" join t_user u ")
                .append("   on o.user_id = u.id ")
                .append(" join t_item i ")
                .append("   on o.id = i.order_id ")
                .append(" join t_product p ")
                .append("   on i.product_id = p.id ")
                .append(" where o.id = ? ")
                .toString();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Order order = null;
        try {
            conn = JDBCUtil.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setInt(1, id);
            rs = ps.executeQuery();
            while (rs.next()) {
                // 一方数据的映射只映射一次
                if (order == null) {
                    order = new Order();
                    order.setId(rs.getLong("id"));
                    order.setNo(rs.getString("no"));
                    order.setPrice(rs.getDouble("price"));
                    order.setCount(rs.getInt("count"));
                    User user = new User();
                    user.setUsername(rs.getString("username"));
                    user.setPhone(rs.getString("phone"));
                    order.setUser(user);
                }

                // 多方数据的映射可以映射多次
                Item item = new Item();
                item.setPrice(rs.getDouble("i.price"));
                item.setNum(rs.getInt("num"));
                Product product = new Product();
                product.setName(rs.getString("name"));
                item.setProduct(product);

                // 将多方数据添加到一方数据的集合属性中
                order.addItem(item);
            }
            return order;
        } catch (Exception e) {
            throw new DataAccessException("数据访问异常");
        }
    }
}
